﻿using Reborn.Infrastructure;
using SimpleSpider.Framework.Model;
using SimpleSpider.Framework.Services;
using SimpleSpider.Framework.Services.Impl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SimpleSpider.Framework
{
    public abstract class CrawlContentWorker : SpiderBase
    {
        UrlService _urlService = null;
        ContentService _contentService = null;

        bool _isStart = false;
        bool isNotData = false;

        public CrawlContentWorker() {
            _urlService = new UrlService();
            _contentService = new ContentService();
        }

        public abstract void Handler(UrlModel urlModel);

        /// <summary>
        /// 保存网址
        /// </summary>
        /// <param name="urlModel"></param>
        /// <returns></returns>
        public int Save(ContentModel contentModel)
        {
            return _contentService.Add(contentModel);
        }

        /// <summary>
        /// 批量保存网址
        /// </summary>
        /// <param name="urls"></param>
        /// <returns></returns>
        public int Save(List<ContentModel> contentModels)
        {
            return _contentService.Insert(contentModels);
        }

        public void Start()
        {
            if (_isStart) return;
            _isStart = true;

            Task.Factory.StartNew(Work);
        }

        void Work()
        {
            while (true)
            {
                try
                {
                    UrlModel urlModel = Pop();
                    if (urlModel == null)
                    {
                        isNotData = true;
                        continue;
                    }

                    isNotData = false;
                    Handler(urlModel);


                    urlModel.UpdateTime = DateTime.Now;

                    _urlService.Update(urlModel, t => new { t.Status, t.UpdateTime });
                }
                catch (Exception ex)
                {
                    Logger.Exception(ex);
                }
                finally
                {
                    Thread.Sleep(50);
                }
            }
        }

        UrlModel Pop()
        {
            var urlResult = _urlService.GetFirst(x => x.Status == Reborn.Contracts.State.TaskStatus.WaitingForActivation);
            if (urlResult == null) return urlResult;

            urlResult.UpdateTime = DateTime.Now;
            urlResult.Status = Reborn.Contracts.State.TaskStatus.WaitingToRun;

            _urlService.Update(urlResult, t => new { t.Status, t.UpdateTime });

            return urlResult;
        }
    }
}
